package com.jbob.tools;

import java.util.HashMap;
import java.util.Iterator;

import com.hp.hpl.jena.graph.impl.Fragments.GetSlot;
import com.jbob.collection.Balise;
import com.jbob.collection.Query;
import com.jbob.collection.Terme;
import com.jbob.constants.CONSTANTS;
import com.jbob.mysql.MySQLHelper;

public class Calculator {

	public static void calculPoids() {

		System.out.println(" -- Calcul du poids --");
		
		// Calcul de l'IEF de chaque terme
		// listIEF contient <terme_id, ief>
		HashMap<Long, Float> listIEF = calculIEF();

		
		// A ce stage, l'IEF de chaque balise est enregistrée

		// **************************************************
		// Calcul du TF
		// Récupération du nombre d'éléments dans chaque balise
		HashMap<Long, Integer> listNbElementByBalise = MySQLHelper.getNbElementByBalise(null);
		
		HashMap<Long, HashMap<Long, Integer>> listFrequences = MySQLHelper.getFrequences();
		
		HashMap<Long, HashMap<Long, Float>> listTBPoids = new HashMap<Long, HashMap<Long, Float>>();
		
		for (Long terme_id : listIEF.keySet()) {
			
			// Calcul du TF
			HashMap<Long, Float> listTF = new HashMap<Long, Float>();
			if (listFrequences.get(terme_id) != null)
			{
				for  (Long balise : listFrequences.get(terme_id).keySet()) {
					float calculTF = ((float)listFrequences.get(terme_id).get(balise) / (float)listNbElementByBalise.get(balise));
					listTF.put(balise, calculTF);
				}
				
				HashMap<Long, Float> listPoids = new HashMap<Long, Float>();
				for (Long balise : listTF.keySet()) {
					float poids = 0;
					if (CONSTANTS.CALCUL_POIDS_FORMULE.equals(CONSTANTS.EnumPoids.TFIEF)) {
						poids = (float) ((float)listTF.get(balise) * listIEF.get(terme_id));
					} else if (CONSTANTS.CALCUL_POIDS_FORMULE.equals(CONSTANTS.EnumPoids.TF)) {
						poids = listTF.get(balise);
					} else if (CONSTANTS.CALCUL_POIDS_FORMULE.equals(CONSTANTS.EnumPoids.IEF)) {
						poids =  listIEF.get(terme_id);
					} 
					
					listPoids.put(balise, poids);
					
				}
	
				listTBPoids.put(terme_id, listPoids);
			}
		}
		
		MySQLHelper.updatePoids(listTBPoids);
		
		
	}
	
	public static HashMap<Long, Float> calculIEF(){

		HashMap<Long, Float> listIEF = new HashMap<Long, Float>();
		
		// Récupération du nombre de balise
		int nbBalises = MySQLHelper.getNbElementTable("balise", "id");
		System.out.println(nbBalises);
		// R�cup�ration de l'IEF de chaque terme
		HashMap<Long, Integer> listIEFDenom = MySQLHelper.getDatabaseIEF();
		
		// Calcul de l'IEF
		for (Long terme : listIEFDenom.keySet()) {
			float calculIEF = (float) Math.log10(nbBalises / (listIEFDenom.get(terme)));
			listIEF.put(terme, calculIEF);
		}
		
		return listIEF;
	}
	
	
	public static double calculCosinus(Balise balise, Query query)
	{
		double res = 0d;
		if(balise != null)
		{
			double numerateur = 0f;
			double denominateur = 0f;
			// Calcul si les termes sont proches les uns des autres
			double termeProche = 0;
			for (Terme t : balise.getTermes()) {
				if(query.getWordsToSeek().contains(t.getNom())) {
					for (Terme t2 : balise.getTermes()) {
//						if(query.getWordsToSeek().contains(t2.getNom())) {
							if (!t.getNom().equals(t2.getNom())) {
								// Split des positions
								String[] termPos = t.getPositions().split(",");
								String[] termPos2 = t2.getPositions().split(",");
								for (String pos : termPos) {
									for (String pos2 : termPos2) {
										if (Math.abs(Integer.valueOf(pos) - Integer.valueOf(pos2)) <= 5) {
											termeProche++;
										}
									}
								}
								
							}
//						}
					}
				}
				
			}
			
			//
			for (Terme t : balise.getTermes()) 
			{
				double mult = 0;
				if(query.getWordsToSeek().contains(t.getNom()))
				{
					//System.out.println("la balise contient le terme réel : " + t.getNom());
					mult = 10;
				}
				else if(query.getSynonymsToSeek().contains(t.getNom()))
				{
					if (query.getSynonymsToSeek().size() < 15) {
						mult = 1 - (query.getSynonymsToSeek().size() * 0.05);
					} else {
						mult = 0.25;
					}
					
					//System.out.println("la balise contient un synonyme : " + t.getNom());
				}
				else if(query.getParentsToSeek().contains(t.getNom()))
				{
					mult = 0.2 / query.getParentsToSeek().size();
				}
				else if(query.getSubClassToSeek().contains(t.getNom()))
				{
					mult = 0.1 / query.getSubClassToSeek().size();
				} else {
					System.out.println(" --- ERROR ----");
					System.out.println(t.getNom());
					System.out.println(query.getParentsToSeek());
					System.out.println(query.getSubClassToSeek());
					System.out.println(" - Le mot n'appartient à aucun groupe de mots -");
					System.exit(0);
				}
				if (mult > 0.0) {
					numerateur += t.getPoids() * mult;
					denominateur += Math.pow(t.getPoids() * mult, 2);
				}
			}
			if(denominateur > 0f) {
				res = numerateur / Math.sqrt(((double)balise.getTermes().size()) * denominateur);
				if (termeProche != 0) {
					//System.out.println("res : " + res);
					double resProche = res - (0.15 * (termeProche));
					res = resProche;
				}
				
				
			}
		}
		return res;
	}
}
